package com.example.huadu_server.admin.service.impl;

import cn.dev33.satoken.secure.BCrypt;
import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.huadu_server.admin.dto.UpdateInfoDTO;
import com.example.huadu_server.admin.dto.UserInfoDTO;
import com.example.huadu_server.admin.entity.Admin;
import com.example.huadu_server.admin.mapper.AdminMapper;
import com.example.huadu_server.appointment.mapper.AppointmentMapper;
import com.example.huadu_server.house.mapper.BrowsingHistoryMapper;
import com.example.huadu_server.house.mapper.FavoriteMapper;
import com.example.huadu_server.house.mapper.HouseMapper;
import com.example.huadu_server.admin.service.AdminService;
import com.example.huadu_server.config.Response;
import com.example.huadu_server.landlord.entity.Landlord;
import com.example.huadu_server.landlord.mapper.LandlordMapper;
import com.example.huadu_server.oss.service.OssService;

import com.example.huadu_server.user.entity.User;
import com.example.huadu_server.user.mapper.UserMapper;
import com.example.huadu_server.websocket.mapper.MessageMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;

import java.util.*;
import java.util.concurrent.TimeUnit;

@Service
public class AdminServiceImpl implements AdminService {

    @Autowired
    private AdminMapper adminMapper;

    @Autowired
    private HouseMapper houseMapper;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private LandlordMapper landlordMapper;

    // 新增预约和消息对应的 Mapper
    @Autowired
    private AppointmentMapper appointmentMapper;

    @Autowired
    private MessageMapper messageMapper;

    @Autowired
    private BrowsingHistoryMapper browsingHistoryMapper;

    @Autowired
    private FavoriteMapper favoriteMapper;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private JavaMailSender mailSender;

    private static final String REDIS_KEY_PREFIX = "FORGET_PASS_CODE_";

    private static final String REDIS_KEY_PREFIX_EMAIL = "UPDATE_EMAIL_CODE_";

    @Value("${spring.mail.username}")  // 从配置文件中注入发件人邮箱
    private String senderEmail;


    /**
     * 修改密码
     * @param adminId
     * @param oldPassword
     * @param newPassword
     * @param confirmPassword
     * @return
     */
    @Override
    public Response<String> modifyPassword(int adminId, String oldPassword, String newPassword, String confirmPassword) {
        // 查询用户信息
        Admin admin = adminMapper.selectById(adminId);
        if (admin == null) {
            return new Response<>(404, "用户不存在", null);
        }

        // 校验旧密码
        if (!BCrypt.checkpw(oldPassword, admin.getPassword())) {
            return new Response<>(400, "原密码错误", null);
        }

        // 校验新密码和确认密码是否一致
        if (!newPassword.equals(confirmPassword)) {
            return new Response<>(400, "新密码与确认密码不一致", null);
        }

        // 校验新密码是否合法
        if (newPassword.length() < 6 || newPassword.length() > 20) {
            return new Response<>(400, "新密码长度应在6到20字符之间", null);
        }

        // 更新密码
        admin.setPassword(BCrypt.hashpw(newPassword, BCrypt.gensalt()));
        int rows = adminMapper.updateById(admin);

        if (rows > 0) {
            return new Response<>(200, "密码修改成功", null);
        } else {
            return new Response<>(500, "密码修改失败，请稍后再试", null);
        }
    }

    /**
     * 重置密码
     * @param email
     * @param code
     * @param newPassword
     * @param confirmPassword
     * @return
     */
    @Override
    public Response<String> resetPassword(String email, String code, String newPassword, String confirmPassword) {
        // 验证码校验
        String redisCode = redisTemplate.opsForValue().get(REDIS_KEY_PREFIX + email);
        if (redisCode == null || !redisCode.equals(code)) {
            return new Response<>(400, "验证码错误或已过期", null);
        }

        // 校验新密码和确认密码是否一致
        if (!newPassword.equals(confirmPassword)) {
            return new Response<>(400, "新密码与确认密码不一致", null);
        }

        // 校验新密码长度
        if (newPassword.length() < 6 || newPassword.length() > 20) {
            return new Response<>(400, "新密码长度应在6到20字符之间", null);
        }

        // 查找用户并更新密码
        Admin admin = adminMapper.selectByEmail(email);
        if (admin == null) {
            return new Response<>(404, "该邮箱未注册", null);
        }

        admin.setPassword(BCrypt.hashpw(newPassword, BCrypt.gensalt()));
        int rows = adminMapper.updateById(admin);

        if (rows > 0) {
            redisTemplate.delete(REDIS_KEY_PREFIX + email); // 删除验证码
            return new Response<>(200, "密码重置成功", null);
        } else {
            return new Response<>(500, "密码重置失败，请稍后再试", null);
        }
    }

    //查看个人信息
    @Override
    public Response<Admin> getUserInfoById(int adminId) {
        // 根据用户 ID 查询用户信息
        Admin admin = adminMapper.selectById(adminId);
        if (admin == null) {
            return new Response<>(404, "用户不存在", null);
        }

        // 返回用户信息
        return new Response<>(200, "查询成功", admin);

    }

    /**
     * 修改用户信息
     */
    @Override
    public Response<String> updateUserInfo(int adminId, UpdateInfoDTO updateInfoDTO) {
        // 查询用户信息
        Admin admin = adminMapper.selectById(adminId);
        if (admin == null) {
            return new Response<>(404, "用户不存在", null);
        }

        // 更新用户信息
        if (updateInfoDTO.getUsername() != null) {
            admin.setUsername(updateInfoDTO.getUsername());
        }
        if (updateInfoDTO.getPhone() != null) {
            admin.setPhone(updateInfoDTO.getPhone());
        }
        if (updateInfoDTO.getGender() != null) {
            admin.setGender(updateInfoDTO.getGender());
        }
        if (updateInfoDTO.getLogo() != null) {
            admin.setLogo(updateInfoDTO.getLogo());
        }

        // 提交更新
        int rows = adminMapper.updateById(admin);
        if (rows > 0) {
            return new Response<>(200, "用户信息修改成功", null);
        } else {
            return new Response<>(500, "用户信息修改失败，请稍后再试", null);
        }
    }

    /**
     * 发送修改邮箱验证码
     * @param email
     * @return
     */
    @Override
    public Response<String> sendUpdateEmailCode(String email) {
        // 检查邮箱是否存在
        Admin admin = adminMapper.selectByEmail(email);
        if (admin != null) {
            return new Response<>(404, "该邮箱已注册", null);
        }

        // 生成验证码
        String code = String.format("%06d", new Random().nextInt(1000000));

        // 存储到 Redis，有效期5分钟
        redisTemplate.opsForValue().set(REDIS_KEY_PREFIX_EMAIL + email, code, 5, TimeUnit.MINUTES);

        // 发送邮件
        SimpleMailMessage message = new SimpleMailMessage();
        message.setFrom(senderEmail); // 发件人地址
        message.setTo(email);
        message.setSubject("花都优居平台");
        message.setText("您的验证码是：" + code + "，用于重置邮箱，有效期为5分钟。");

        try {
            mailSender.send(message);
            return new Response<>(200, "验证码已发送，请查收", code);
        } catch (Exception e) {
            return new Response<>(500, "发送验证码失败，请稍后再试", null);
        }
    }


    /**
     * 修改用户邮箱
     */
    @Override
    public Response<String> updateUserEmail(int adminId, UserInfoDTO adminInfoDTO) {
        // 查询用户信息
        Admin admin = adminMapper.selectById(adminId);
        if (admin == null) {
            return new Response<>(404, "用户不存在", null);
        }

        // 验证码校验
        String redisCode = redisTemplate.opsForValue().get(REDIS_KEY_PREFIX_EMAIL + adminInfoDTO.getEmail());
        if (redisCode == null || !redisCode.equals(adminInfoDTO.getCode())) {
            return new Response<>(400, "验证码错误或已过期", null);
        }

        // 更新用户信息
        if (adminInfoDTO.getEmail() != null) {
            admin.setEmail(adminInfoDTO.getEmail());
        }

        // 提交更新
        int rows = adminMapper.updateById(admin);
        if (rows > 0) {
            return new Response<>(200, "用户信息修改成功", null);
        } else {
            return new Response<>(500, "用户信息修改失败，请稍后再试", null);
        }
    }

    @Override
    public Response<String> sendForgetPasswordCode(String email) {
        // 检查邮箱是否存在
        Admin admin = adminMapper.selectByEmail(email);
        if (admin == null) {
            return new Response<>(404, "该邮箱未注册", null);
        }

        // 生成验证码
        String code = String.format("%06d", new Random().nextInt(1000000));

        // 存储到 Redis，有效期5分钟
        redisTemplate.opsForValue().set(REDIS_KEY_PREFIX + email, code, 5, TimeUnit.MINUTES);

        // 发送邮件
        SimpleMailMessage message = new SimpleMailMessage();
        message.setFrom(senderEmail); // 发件人地址
        message.setTo(email);
        message.setSubject("花都优居平台");
        message.setText("您的验证码是：" + code + "，用于重置密码，有效期为5分钟。");

        try {
            mailSender.send(message);
            return new Response<>(200, "验证码已发送，请查收", code);
        } catch (Exception e) {
            return new Response<>(500, "发送验证码失败，请稍后再试", null);
        }
    }

    /**
     * 上传用户头像
     */
    @Autowired
    private OssService ossService;

    @Override
    public Response<String> uploadUserLogo(@RequestParam("file") MultipartFile file, int adminId) {
        try {
            // 调用 OssService 上传文件
            String fileUrl = ossService.uploadFile(file, "AdminLogo");

            // 替换 HTTPS 为 HTTP
            fileUrl = fileUrl.replace("https://", "http://");

            // 更新数据库中用户头像字段
            Admin admin = adminMapper.selectById(adminId);
            if (admin == null) {
                return new Response<>(404, "用户不存在", null);
            }
            admin.setLogo(fileUrl);
            adminMapper.updateById(admin);

            return new Response<>(200, "头像上传成功", fileUrl);
        } catch (RuntimeException e) {
            return new Response<>(500, e.getMessage(), null);
        }
    }


    /**
     * 获取所有用户
     *
     * @return 用户列表
     */
    @Override
    public Response<Map<String, Object>> getAllUsers(int pageNo, int pageSize) {
        // 确保页码合法
        if (pageNo < 1) {
            pageNo = 1;
        }
        int offset = (pageNo - 1) * pageSize;

        // 查询总数：所有用户
        QueryWrapper<User> countWrapper = new QueryWrapper<>();
        int total = Math.toIntExact(userMapper.selectCount(countWrapper));

        // 分页查询：所有用户
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("id", "username", "email", "phone", "logo", "gender", "career", "status")
                .last("LIMIT " + offset + ", " + pageSize);
        List<User> userList = userMapper.selectList(queryWrapper);

        Map<String, Object> result = new HashMap<>();
        result.put("total", total);
        result.put("userList", userList);
        result.put("pageNo", pageNo);
        result.put("pageSize", pageSize);
        // 返回分页数据
        return new Response<>(200, "查询成功", result);
    }

    @Override
    public Response<Map<String, Object>> getAllLandlords(int pageNo, int pageSize) {
        // 确保页码合法
        if (pageNo < 1) {
            pageNo = 1;
        }
        int offset = (pageNo - 1) * pageSize;

        // 查询总数：所有房东
        QueryWrapper<Landlord> countWrapper = new QueryWrapper<>();
        int total = Math.toIntExact(landlordMapper.selectCount(countWrapper));

        // 分页查询：所有房东
        QueryWrapper<Landlord> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("id", "username", "phone", "email", "logo", "gender", "status")
                .last("LIMIT " + offset + ", " + pageSize);
        List<Landlord> landlordList = landlordMapper.selectList(queryWrapper);

        Map<String, Object> result = new HashMap<>();
        result.put("total", total);
        result.put("landlordList", landlordList);
        result.put("pageNo", pageNo);
        result.put("pageSize", pageSize);
        // 返回分页数据
        return new Response<>(200, "查询成功", result);
    }

    /**
     * 禁用用户
     *
     * @param userId   用户ID
     * @param password 管理员密码
     * @param remarks  禁用理由（邮件通知内容）
     * @return 操作结果
     */
    @Override
    public Response<String> disableUser(int userId, String password, String remarks) {
        // 校验管理员密码
        if (!checkAdminPassword(password)) {
            return new Response<>(400, "管理员密码错误", null);
        }

        User user = userMapper.selectById(userId);
        if (user == null) {
            return new Response<>(404, "用户不存在", null);
        }

        // 校验是否已禁用
        if ("disabled".equals(user.getStatus())) {
            return new Response<>(400, "该用户已被禁用，请刷新页面", null);
        }

        // 更新用户状态为禁用
        user.setStatus("disabled");
        userMapper.updateById(user);

        // 发送邮件通知
        String userEmail = user.getEmail();
        sendEmail(userEmail, "账号禁用通知", "您的账号已被禁用，禁用理由：" + remarks+"\n如有疑问请回复此邮件");

        return new Response<>(200, "禁用成功", null);
    }

    /**
     * 恢复用户
     *
     * @param userId   用户ID
     * @param password 管理员密码
     * @return 操作结果
     */
    @Override
    public Response<String> enableUser(int userId, String password) {
        // 校验管理员密码
        if (!checkAdminPassword(password)) {
            return new Response<>(400, "管理员密码错误", null);
        }

        User user = userMapper.selectById(userId);
        if (user == null) {
            return new Response<>(404, "用户不存在", null);
        }

        // 校验是否已恢复
        if ("normal".equals(user.getStatus())) {
            return new Response<>(400, "该用户已是正常状态，请刷新页面", null);
        }

        // 更新用户状态为正常
        user.setStatus("normal");
        userMapper.updateById(user);

        // 发送邮件通知
        String userEmail = user.getEmail();
        sendEmail(userEmail, "账号恢复通知", "您的账号已恢复正常。");

        return new Response<>(200, "恢复成功", null);
    }

    /**
     * 禁用房东
     *
     * @param landlordId 房东ID
     * @param password   管理员密码
     * @param remarks    禁用理由（邮件通知内容）
     * @return 操作结果
     */
    @Override
    public Response<String> disableLandlord(int landlordId, String password, String remarks) {
        // 校验管理员密码
        if (!checkAdminPassword(password)) {
            return new Response<>(400, "管理员密码错误", null);
        }

        Landlord landlord = landlordMapper.selectById(landlordId);
        if (landlord == null) {
            return new Response<>(404, "房东不存在", null);
        }

        // 校验是否已禁用
        if ("disabled".equals(landlord.getStatus())) {
            return new Response<>(400, "该房东已被禁用，请刷新页面", null);
        }

        // 更新房东状态为禁用
        landlord.setStatus("disabled");
        landlordMapper.updateById(landlord);

        // 发送邮件通知
        String landlordEmail = landlord.getEmail();
        sendEmail(landlordEmail, "账号禁用通知", "您的账号已被禁用，禁用理由：" + remarks+"\n如有疑问请回复此邮件");

        return new Response<>(200, "禁用成功", null);
    }

    /**
     * 恢复房东
     *
     * @param landlordId 房东ID
     * @param password   管理员密码
     * @return 操作结果
     */
    @Override
    public Response<String> enableLandlord(int landlordId, String password) {
        // 校验管理员密码
        if (!checkAdminPassword(password)) {
            return new Response<>(400, "管理员密码错误", null);
        }

        Landlord landlord = landlordMapper.selectById(landlordId);
        if (landlord == null) {
            return new Response<>(404, "房东不存在", null);
        }

        // 校验是否已恢复
        if ("normal".equals(landlord.getStatus())) {
            return new Response<>(400, "该房东已是正常状态，请刷新页面", null);
        }

        // 更新房东状态为正常
        landlord.setStatus("normal");
        landlordMapper.updateById(landlord);

        // 发送邮件通知
        String landlordEmail = landlord.getEmail();
        sendEmail(landlordEmail, "账号恢复通知", "您的账号已恢复正常。");

        return new Response<>(200, "恢复成功", null);
    }


    /**
     * 发送邮件通知
     * @param email 收件人邮箱
     * @param subject 邮件主题
     * @param content 邮件内容
     */
    private void sendEmail(String email, String subject, String content) {
        // 邮件发送逻辑，使用 JavaMailSender 等发送邮件
        SimpleMailMessage message = new SimpleMailMessage();
        message.setFrom(senderEmail);  // 发件人邮箱
        message.setTo(email);
        message.setSubject(subject);
        message.setText(content);
        mailSender.send(message);
    }


    /**
     * 校验管理员密码
     *
     * @param password 管理员输入的密码
     * @return 是否验证通过
     */
    private boolean checkAdminPassword(String password) {
        // 通过 Sa-Token 获取当前登录管理员的 ID
        int adminId = StpUtil.getLoginIdAsInt();

        // 查询管理员记录
        Admin admin = adminMapper.selectById(adminId);

        // 如果管理员不存在或其密码为空，则返回 false
        if (admin == null || admin.getPassword() == null) {
            return false;
        }

        // 使用 BCrypt 校验明文密码与加密密码是否匹配
        return BCrypt.checkpw(password, admin.getPassword());
    }


    /**
     * 获取概览统计信息
     * @return
     */
    @Override
    public Response<Map<String, Object>> getOverviewStats() {
        // 查询总租客数
        int totalUsers = Math.toIntExact(userMapper.selectCount(new QueryWrapper<User>()));
        // 查询总房东数
        int totalLandlords = Math.toIntExact(landlordMapper.selectCount(new QueryWrapper<Landlord>()));
        // 查询房源总量
        int totalHouses = Math.toIntExact(houseMapper.selectCount(new QueryWrapper<>()));
        // 查询预约记录数量
        int totalAppointments = Math.toIntExact(appointmentMapper.selectCount(new QueryWrapper<>()));
        // 查询在线聊天记录数量
        int totalMessages = Math.toIntExact(messageMapper.selectCount(new QueryWrapper<>()));

        Map<String, Object> data = new HashMap<>();
        data.put("totalUsers", totalUsers);
        data.put("totalLandlords", totalLandlords);
        data.put("totalHouses", totalHouses);
        data.put("totalAppointments", totalAppointments);
        data.put("totalMessages", totalMessages);

        return new Response<>(200, "统计数据查询成功", data);
    }

    /**
     * 获取趋势统计数据的实现
     * 根据 type 参数调用对应的 mapper 自定义查询方法
     */
    @Override
    public Response<Map<String, Object>> getTrendStats(String type, String startDate, String endDate, String granularity) {
        List<Map<String, Object>> trendData = null;
        switch (type.toLowerCase()) {
            case "house":
                // 通过 houseMapper 调用自定义方法查询房源趋势数据
                trendData = houseMapper.selectTrendStats(startDate, endDate, granularity);
                break;
            case "appointment":
                // 通过 appointmentMapper 调用自定义方法查询预约趋势数据
                trendData = appointmentMapper.selectTrendStats(startDate, endDate, granularity);
                break;
            case "message":
                // 通过 messageMapper 调用自定义方法查询消息趋势数据
                trendData = messageMapper.selectTrendStats(startDate, endDate, granularity);
                break;
            default:
                return new Response<>(400, "不支持的趋势数据类型", null);
        }
        Map<String, Object> data = new HashMap<>();
        data.put("trendData", trendData);
        return new Response<>(200, "趋势数据查询成功", data);
    }

    /**
     * 获取用户行为统计
     * @return
     */

    @Override
    public Response<Map<String, Object>> getUserBehaviorStats(String metric, String startDate, String endDate, String granularity) {
        Map<String, Object> result = new HashMap<>();
        switch (metric.toLowerCase()) {
            case "browse":
                List<Map<String, Object>> browseData = browsingHistoryMapper.selectTrendStats(startDate, endDate, granularity);
                result.put("trendData", browseData);
                break;
            case "favorite":
                List<Map<String, Object>> favoriteData = favoriteMapper.selectTrendStats(startDate, endDate, granularity);
                result.put("trendData", favoriteData);
                break;
            case "appointment":
                List<Map<String, Object>> appointmentData = appointmentMapper.selectTrendStats(startDate, endDate, granularity);
                result.put("trendData", appointmentData);
                break;
            case "conversion":
                // 分别查询浏览与预约趋势数据，再计算转化率（预约数/浏览数）
                List<Map<String, Object>> browseTrend = browsingHistoryMapper.selectTrendStats(startDate, endDate, granularity);
                List<Map<String, Object>> appointmentTrend = appointmentMapper.selectTrendStats(startDate, endDate, granularity);
                List<Map<String, Object>> conversionTrend = new ArrayList<>();
                // 假设两个列表的 period 完全一致
                for (int i = 0; i < browseTrend.size(); i++) {
                    Map<String, Object> bMap = browseTrend.get(i);
                    Map<String, Object> aMap = appointmentTrend.get(i);
                    String period = (String) bMap.get("period");
                    int browseCount = ((Number) bMap.get("count")).intValue();
                    int appointmentCount = ((Number) aMap.get("count")).intValue();
                    double conversion = browseCount > 0 ? (appointmentCount * 1.0 / browseCount) : 0;
                    Map<String, Object> dataPoint = new HashMap<>();
                    dataPoint.put("period", period);
                    // 此处保留两位小数，但你可以转换为整数后显示百分比，如 Math.round(conversion * 100)
                    dataPoint.put("count", conversion);
                    conversionTrend.add(dataPoint);
                }
                result.put("trendData", conversionTrend);
                break;
            default:
                return new Response<>(400, "不支持的统计指标", null);
        }
        return new Response<>(200, "用户行为统计数据查询成功", result);
    }

    /**
     * 获取房东运营情况:统计每个房东的房源发布数量及预约记录数量，帮助评估房东运营情况
     * @return
     */
    @Override
    public Response<List<Map<String, Object>>> getLandlordPerformanceStats() {
        List<Map<String, Object>> performanceData = landlordMapper.selectLandlordPerformance();
        return new Response<>(200, "房东运营情况数据查询成功", performanceData);
    }

    /**
     * 获取地理分布统计数据
     * @param type 统计类型，"business" 表示按商圈统计，"subway" 表示按地铁站统计
     * @return
     */
    @Override
    public Response<List<Map<String, Object>>> getGeoDistribution(String type) {
        List<Map<String, Object>> distribution;
        if ("business".equalsIgnoreCase(type)) {
            distribution = houseMapper.selectDistributionByBusinessArea();
        } else if ("subway".equalsIgnoreCase(type)) {
            distribution = houseMapper.selectDistributionBySubwayStation();
        } else {
            return new Response<>(400, "不支持的统计类型，请选择 business 或 subway", null);
        }
        return new Response<>(200, "地理分布统计数据查询成功", distribution);
    }
}

